package com.googlecode.intellimars.sabotter;

import com.googlecode.intellimars.sabotter.ui.SabotterWindow;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.util.net.HttpConfigurable;
import twitter4j.Twitter;
import twitter4j.TwitterException;

import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.net.Authenticator;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

// TODO: 設定がプロジェクトごとに必要というのがなんとも（それでもいっか）
@State(
    name = "SabotterPlugin",
    storages = { @Storage(id = "sabotter", file = "$WORKSPACE_FILE$") }
)
public class SabotterPlugin extends SabotterProjectComponent {
    private static final Logger LOG = Logger.getInstance("sabotter");

    private Twitter twitter;
    private Runnable monitorThread;
    private ScheduledExecutorService exeService;
    private ScheduledFuture future;
    public TimeLineWrapper timeLine;


    public static SabotterPlugin getInstance(Project project) {
        return project.getComponent(SabotterPlugin.class);
    }

    public SabotterPlugin(Project project) {
        super(project);
        sabotterWindow = new SabotterWindow(this);
        exeService = Executors.newScheduledThreadPool(1);
    }

    public boolean signIn() {
        // proxy設定を有効にする
        prepareURL();

        LOG.info("login:" + config);
        twitter = new Twitter(config.getUsername(), config.getPassword(), config.getServerUrl());
        // しゃべる(shovel)では，account/verify_credentials.formatが未実装のため，あえてやらない。
//        if (!twitter.verifyCredentials()) {
//            return false;
//        }

        try {
            // 初回だけRepliesを取り込む（キレイな実装じゃないなぁ）
            timeLine = new TimeLineWrapper(config, twitter.getReplies());
        }
        catch (TwitterException e) {
            LOG.error(e);
        }

        if (config.getInterval() > 0) {
            future = exeService.scheduleAtFixedRate(monitorThread = new TimeLineUpdater(),
                                                    0, config.getInterval(), TimeUnit.SECONDS);
        }
        else {
            // 自動更新しない場合も，初回だけメッセージを取り込む
            try {
                updateTimeLine();
            }
            catch (TwitterException e) {
                LOG.error(e);
            }
        }
        return true;
    }

    private void prepareURL() {
        if (!config.isUseProxy()) {
            System.setProperty("proxySet", "false");
            Authenticator.setDefault(null);
            return;
        }

        HttpConfigurable httpConfig = HttpConfigurable.getInstance();
        try {
            // IntelliJのproxy設定を有効にする
            httpConfig.prepareURL(config.getServerUrl());

            if (httpConfig.USE_HTTP_PROXY) {
                // ついでに https でも有効にしておく
                System.setProperty("https.proxyHost", httpConfig.PROXY_HOST);
                System.setProperty("https.proxyPort", Integer.toString(httpConfig.PROXY_PORT));
            }
        }
        catch (IOException ignore) { }
    }


    public synchronized void signOut() {
        sabotterWindow.deactivate();
        if (future != null) future.cancel(true);
        monitorThread = null;
        twitter = null;
    }

    public synchronized void updateTimeLine() throws TwitterException {
        // 正直，メッセージの取りこぼしはご愛嬌としたい。:-P
        timeLine.add(twitter.getFriendsTimeline());

        // Viewを更新する
        sabotterWindow.updateTimeLine();

        if (timeLine.hasNewMessage()) {
            // 色気出して新着メッセージをポップアップ
            // TODO:このポップアップもOn/Offできたほうがいいかしらん？
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    /* Balloonのサンプル実装 ... まだまだ研究しないと
                    ToolWindowManager.getInstance(project).notifyByBalloon(TOOL_WINDOW_ID, MessageType.INFO, timeLine.whatNew());
                    
                    BalloonBuilder builder = JBPopupFactory.getInstance().createBalloonBuilder(new JEditorPane("text/html", timeLine.whatNew()));
                    BalloonBuilder builder = JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(timeLine.whatNew(), null, Color.WHITE, null);
                    Balloon balloon = builder.createBalloon();
                    balloon.show(new RelativePoint(sabotterWindow.rootPanel,
                                                   new Point(sabotterWindow.rootPanel.getWidth(),
                                                             sabotterWindow.rootPanel.getHeight())),
                                 Balloon.Position.above);
                    */
                    
                    WindowManager.getInstance()
                            .getStatusBar(project)
                            .fireNotificationPopup(
                                    new JEditorPane("text/html", timeLine.whatNew()),
                                    Color.DARK_GRAY
                            );
                }
            });
        }
    }

    public void projectClosed() {
        super.projectClosed();
        signOut();
        exeService.shutdown();
    }


    public void sendMessage(String text) {
        if (twitter == null) return;
        try {
            // updateできてもtimelineは更新しないことにする
            twitter.update(text);
        }
        catch (TwitterException e) {
            LOG.error(e);
        }
    }

    private class TimeLineUpdater implements Runnable {
        public void run() {
            try {
                updateTimeLine();
            }
            catch (Exception e) {
                LOG.error(e);
            }
        }
    }
}
